﻿using System;

namespace SpatialHashLib.Topology
{
    public struct Extent : ISpatialKey
    {
        static Extent empty = new Extent(Coord.Empty, Coord.Empty);

        public static Extent Empty { get { return empty; } }

        Coord min;
        Coord max;

        public Extent(Coord p0, Coord p1)
        {
            min = new Coord(
                p0.X < p1.X ? p0.X : p1.X,
                p0.Y < p1.Y ? p0.Y : p1.Y
                );

            max = new Coord(
                p1.X > p0.X ? p1.X : p0.X,
                p1.Y > p0.Y ? p1.Y : p0.Y
                );
        }

        public Extent(Coord center, double width, double height)
        {
            min = new Coord(
                center.X - width / 2,
                center.Y - height / 2
                );

            max = new Coord(
                center.X + width / 2,
                center.Y + height / 2
                );
        }

        public bool IsEmpty { get { return min.IsEmpty || max.IsEmpty; } }

        public Coord Min { get { return min; } }
        public Coord Max { get { return max; } }

        public Coord Center
        {
            get
            {
                return new Coord(
                    min.X + (max.X - min.X) * 0.5,
                    min.Y + (max.Y - min.Y) * 0.5
                    );
            }
        }

        public double Width
        {
            get { return (max.X - min.X); }
        }

        public double Height
        {
            get { return (max.Y - min.Y); }
        }

        public double Size
        {
            get { return Math.Max(Width, Height); }
        }

        Extent ISpatialKey.Extent
        {
            get { return this; }
        }

        public Extent Translate(Coord translation)
        {
            return new Extent(
                min + translation,
                max + translation
                );
        }

        public Extent Scale(double amount)
        {
            return new Extent(
                Center,
                Width * amount,
                Height * amount
                );
        }

        public Extent Intersection(Extent extent)
        {
            if (!Intersects(extent))
                return Empty;

            return new Extent(
                new Coord(
                    Math.Max(min.X, extent.min.X),
                    Math.Max(min.Y, extent.min.Y)
                    ),
                new Coord(
                    Math.Min(max.X, extent.max.X),
                    Math.Min(max.Y, extent.max.Y)
                    )
                );
        }

        public bool Intersects(Extent extent)
        {
            return !
                (
                    extent.max.X < min.X ||
                    extent.min.X > max.X ||
                    extent.max.Y < min.Y ||
                    extent.min.Y > max.Y
                )
                ;
        }
    }
}
